/*
 * Copyright (c) 2024 AlgoIdeas <yu19881234@163.com>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "securec.h"
#include "common_def.h"
#include "soc_osal.h"
#include "app_init.h"

#include "bts_gatt_server.h"
#include "ble_server.h"

#define BLE_TASK_PRIO                  28
#define BLE_TASK_STACK_SIZE            0x1200
#define BLE_BT_STACK_POWER_MS           10000

typedef struct {
    uint8_t *value;
    uint16_t value_len;
} msg_data_t;
unsigned long mouse_msg_queue = 0;
unsigned int msg_rev_size = sizeof(msg_data_t);

void ble_register_receive_callback(ble_server_register_receive_read_callback read_callback, 
        ble_server_register_receive_write_callback write_callback)
{
    ble_server_register_receive_callback(read_callback, write_callback);
}

void ble_send(const void *buffer, uint16_t length)
{
    if (ble_get_connection_state() != 0) {
        msg_data_t msg_data = { 0 };
        void* buffer_cpy = osal_vmalloc(length);
        if (memcpy_s(buffer_cpy, length, buffer, length) != EOK) {
            osal_vfree(buffer_cpy);
            return;
        }
        msg_data.value = (uint8_t *)buffer_cpy;
        msg_data.value_len = length;
        osal_msg_queue_write_copy(mouse_msg_queue, (void *)&msg_data, msg_rev_size, 0);
    }
}

static void *ble_server_task(const char *arg)
{
    unused(arg);
    ble_server_init();

    while (1) {
        msg_data_t msg_data = { 0 };
        int msg_ret = osal_msg_queue_read_copy(mouse_msg_queue, &msg_data, &msg_rev_size, OSAL_WAIT_FOREVER);
        if (msg_ret != OSAL_SUCCESS) {
            osal_printk("msg queue read copy fail.");
            if (msg_data.value != NULL) {
                osal_vfree(msg_data.value);
            }
            continue;
        }

        if (msg_data.value != NULL) {
            ble_server_send_input_report(msg_data.value, msg_data.value_len);
            osal_vfree(msg_data.value);
        }
    }

    return NULL;
}

static void ble_entry(void)
{
    osal_printk("ble_entry.\r\n");
    int msg_ret = osal_msg_queue_create("task_msg", msg_rev_size, &mouse_msg_queue, 0, msg_rev_size);
    if (msg_ret != OSAL_SUCCESS) {
        osal_printk("msg queue create fail.");
        return;
    }
    osal_task *task_handle = NULL;
    osal_kthread_lock();
    task_handle = osal_kthread_create((osal_kthread_handler)ble_server_task, 0, "BLEServerTask",
                                      BLE_TASK_STACK_SIZE);
    if (task_handle != NULL) {
        osal_kthread_set_priority(task_handle, BLE_TASK_PRIO);
    }
    osal_kthread_unlock();
}

/* Run the ble_entry. */
app_run(ble_entry);
